﻿/*
 * Property.h
 *
 */

#ifndef __GDK_PROPERTY_H__
#define __GDK_PROPERTY_H__


#include <gdk/core/Types.h>
#include <gdk/core/cpptypeid.h>
#include <gdk/core/Unknown.h>
#include <gdk/core/Varint.h>
#include <gdk/core/String.h>
#include <gdk/core/Exception.h>
#include <gdk/core/Mutex.h>
#include <gdk/core/convert.h>
#include <gdk/core/stdlib.h>
#include <gdk/core/SharedPtr.h>
#include <gdk/core/Log.h>
#include <gdk/core/IO.h>
#include <gdk/core/Json.h>

#include <algorithm>
#include <utility>
#include <vector>
#include <list>
#include <map>


namespace gdk
{


////////////////////////////////////////////////////////////////
//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, bool &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const bool &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, float &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const float &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, double &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const double &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, char &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const char &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, long &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const long &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, ulong_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const ulong_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, long long &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const long long &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, unsigned long long &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const unsigned long long &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, int8_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const int8_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, uint8_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const uint8_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, int16_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const int16_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, uint16_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const uint16_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, int32_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const int32_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, uint32_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const uint32_t &value, JsonValue &json) __THROW1
{
	json = value;
}

/*
//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, int64_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const int64_t &value, JsonValue &json) __THROW1
{
	json = value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, uint64_t &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const uint64_t &value, JsonValue &json) __THROW1
{
	json = value;
}
*/

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, Varint &value) __THROW1
{
	value = (ssize_t)json;
}
__INLINE__ void convertPropertyToJson(const Varint &value, JsonValue &json) __THROW1
{
	json = (ssize_t)value;
}

//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, Varint64 &value) __THROW1
{
	value = (int64_t)json;
}
__INLINE__ void convertPropertyToJson(const Varint64 &value, JsonValue &json) __THROW1
{
	json = (int64_t)value;
}

////--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue &json, String &value) __THROW1
{
	value = json;
}
__INLINE__ void convertPropertyToJson(const String &value, JsonValue &json) __THROW1
{
	json = value;
}


/////////////////////////////////////////////////////
class Property;


/////////////////////////////////////////////////////
extern GDK_CORE_EXPORT const String TEXT_class;


/////////////////////////////////////////////////////
template<typename TyClass>
TyClass* Property_cast(const Property *o)
{
	return dynamic_cast<TyClass*>((Property*)o);
}



class GDK_CORE_EXPORT IPropertyConverter : virtual public Unknown
{
	DECLARE_CLASS_HANDLE(IPropertyConverter)

private:
	String	_rttiClassName;
	String	_propertyType;
	bool	_isUnitProperty;


protected:
	IPropertyConverter(const String &rttiClassName, const String &propertyType, bool isUnitProperty);

public:
	__INLINE__ const String& getRttiClassName(void) const { return _rttiClassName; }
	__INLINE__ const String& getPropertyType(void) const { return _propertyType; }
	__INLINE__ bool isUnitProperty(void) const { return _isUnitProperty; }

public:
	virtual void importProperty(void *p, const JsonValue &json) __THROW1 =0;
	virtual void exportProperty(const void *p, JsonValue &json) __THROW1 =0;
};


class PropertyFactory
{
public:
	GDK_CORE_EXPORT static bool setUpPropertyConverter(IPropertyConverter *);
	GDK_CORE_EXPORT static void tearDownPropertyConverter(const String &propertyType);
	GDK_CORE_EXPORT static IPropertyConverter* getPropertyConverter(const String &propertyType);
	GDK_CORE_EXPORT static IPropertyConverter* getPropertyConverterByRttiClassName(const String &rttiClassName);
};


template<typename TyClass>
class PropertyConverterUnit : public IPropertyConverter
{
	DECLARE_CLASS_HANDLE(PropertyConverterUnit)
	DECLARE_CLASS_INSTANCE1(PropertyConverterUnit, const String &)

private:
	PropertyConverterUnit(const String &propertyType)
		: IPropertyConverter(
			typeid_className<TyClass>(),
			propertyType,
			true
		)
	{}

public:
	virtual void importProperty(void *p, const JsonValue &json) __THROW1
	{
		TyClass *o = (TyClass*)p;
		*o = TyClass();
		convertPropertyToClass(json, *o);
	}
	virtual void exportProperty(const void *p, JsonValue &json) __THROW1
	{
		const TyClass *o = (const TyClass *)p;
		convertPropertyToJson(*o, json);
	}
};


template<typename TyClass>
class PropertyConverter : public IPropertyConverter
{
	DECLARE_CLASS_HANDLE(PropertyConverter)
	DECLARE_CLASS_INSTANCE1(PropertyConverter, const String &)

private:
	PropertyConverter(const String &propertyType)
		: IPropertyConverter(
			typeid_className<TyClass>(),
			propertyType,
			false
		)
	{}


public:
	virtual void importProperty(void *p, const JsonValue &json) __THROW1
	{
		typedef typename gdk::Unknown::Handle_T<TyClass> TyClass_Handle;
		TyClass_Handle &o = *(TyClass_Handle*)p;

		if (!json.isNull())
		{
			o = TyClass::createInstance();
			o->importProperty(json);
		}
		else if (o != NULL)
		{
			o = NULL;
		}
	}
	virtual void exportProperty(const void *p, JsonValue &json) __THROW1
	{
		typedef typename gdk::Unknown::Handle_T<const TyClass> TyClass_Handle;

		TyClass_Handle &o = *(TyClass_Handle*)p;
		if (o != NULL)
			o->exportProperty(json);
		else
			json.clear();
	}
};




#define REGISTER_PROPERTY_CONVERTER(PropertyType) \
	static void tearDownPropertyConverter_##PropertyType(void)\
	{\
		gdk::PropertyFactory::tearDownPropertyConverter(__TEXT__(#PropertyType));\
	}\
	static bool setUpPropertyConverter_##PropertyType(void)\
	{\
		bool result = gdk::PropertyFactory::setUpPropertyConverter(PropertyConverter_##PropertyType::createInstance(__TEXT__(#PropertyType)));\
		if (result)\
		{\
			::atexit(tearDownPropertyConverter_##PropertyType);\
		}\
		return result;\
	}\
	static bool g_setUpPropertyConverter_##PropertyType = (gdk::nothing(&g_setUpPropertyConverter_##PropertyType), setUpPropertyConverter_##PropertyType());


#define REGISTER_PROPERTY_CONVERTER_UNIT_X(PropertyType) \
	typedef gdk::PropertyConverterUnit<PropertyType##Array> PropertyConverter_##PropertyType##Array;\
	typedef gdk::PropertyConverterUnit<PropertyType##List>  PropertyConverter_##PropertyType##List;\
	REGISTER_PROPERTY_CONVERTER(PropertyType##Array);\
	REGISTER_PROPERTY_CONVERTER(PropertyType##List);

#define REGISTER_PROPERTY_CONVERTER_UNIT(PropertyType) \
	typedef std::vector<PropertyType>                  PropertyType##Array;\
	typedef std::list<PropertyType>                    PropertyType##List;\
	typedef gdk::PropertyConverterUnit<PropertyType>   PropertyConverter_##PropertyType;\
	REGISTER_PROPERTY_CONVERTER(PropertyType);\
	REGISTER_PROPERTY_CONVERTER_UNIT_X(PropertyType);

#define REGISTER_PROPERTY_CONVERTER_OBJECT(PropertyType) \
	typedef std::vector<PropertyType::Handle>     PropertyType##Array;\
	typedef std::list<PropertyType::Handle>       PropertyType##List;\
	typedef gdk::PropertyConverter<PropertyType>  PropertyConverter_##PropertyType;\
	REGISTER_PROPERTY_CONVERTER(PropertyType);\
	REGISTER_PROPERTY_CONVERTER_UNIT_X(PropertyType);\
	static bool g_setUpPropertyConverter_##PropertyType##_check = (gdk::nothing(&g_setUpPropertyConverter_##PropertyType##_check), GDK_ASSERT(PropertyType::createInstance()->getClassName() == __TEXT__(#PropertyType)), true);



class GDK_CORE_EXPORT IPropertyAttribute : virtual public Unknown
{
	DECLARE_CLASS_HANDLE(IPropertyAttribute)

private:
	static String	_nullString;

private:
	String			_rttiClassName;
	String			_propertyRawName;
	String			_propertyName;
	String			_description;
	bool			_isUnitProperty;

protected:
	IPropertyAttribute(	const String& rttiClassName,
						const String& propertyRawName,
						const String& propertyName,
						const String& description,
						bool          isUnitProperty
						);


public:
	__INLINE__ const String& getPropertyType(void) const
	{
		IPropertyConverter *propertyConverter = getPropertyConverter();
		return (propertyConverter != NULL ? propertyConverter->getPropertyType() : _nullString);
	}
	__INLINE__ IPropertyConverter* getPropertyConverter(void) const
	{
		return PropertyFactory::getPropertyConverterByRttiClassName(_rttiClassName);
	}
	__INLINE__ const String& getRttiClassName(void) const { return _rttiClassName; }
	__INLINE__ const String& getPropertyName(void) const { return _propertyName; }
	__INLINE__ const String& getPropertyRawName(void) const { return _propertyRawName; }
	__INLINE__ const String& getDescription(void) const { return _description; }
	__INLINE__ bool isUnitProperty(void) const { return _isUnitProperty; }

public:
	virtual void set(Property *o, IPropertyConverter *propertyConverter, const JsonValue &json) __THROW1 =0;
	virtual void get(const Property *o, IPropertyConverter *propertyConverter, JsonValue &json) __THROW1 =0;
};


//-----------------------------------------------
GDK_CORE_EXPORT void PropertyAttribute_set(IPropertyAttribute *propertyAttribute, Void *o, IPropertyConverter *propertyConverter, const JsonValue &json) __THROW1;
GDK_CORE_EXPORT void PropertyAttribute_get(IPropertyAttribute *propertyAttribute, const Void *o, IPropertyConverter *propertyConverter, JsonValue &json) __THROW1;


template<typename Ty>
void PropertyAttribute_set(IPropertyAttribute *propertyAttribute, Ty *o, IPropertyConverter *propertyConverter, const JsonValue &json) __THROW1
{
	/*
	Ty v;
	PropertyAttribute_set(propertyAttribute, (Void*)&v, propertyConverter, json);
	*o = v;
	*/
	PropertyAttribute_set(propertyAttribute, (Void*)o, propertyConverter, json);
}

template<typename TyClass, typename TyProperty>
class PropertyAttribute : public IPropertyAttribute
{
	typedef TyProperty(TyClass::*Member);

	DECLARE_CLASS_HANDLE(PropertyAttribute)
	DECLARE_CLASS_INSTANCE6(PropertyAttribute, Member, const String &, const String &, const String &, const String &, bool)

private:
	Member	_propertyMember;

private:
	PropertyAttribute(
			Member        propertyMember,
			const String& rttiClassName,
			const String& propertyRawName,
			const String& propertyName,
			const String& description,
			bool          isUnitProperty
		)
		: IPropertyAttribute(
			rttiClassName,
			propertyRawName,
			propertyName,
			description,
			isUnitProperty
		)
		,_propertyMember(propertyMember)
	{
	}

public:
	virtual void set(Property *o, IPropertyConverter *propertyConverter, const JsonValue &json) __THROW1
	{
		TyClass *p = Property_cast<TyClass>(o);

		GDK_ASSERT(p != NULL);

		PropertyAttribute_set<TyProperty>(this, &(p->*_propertyMember), propertyConverter, json);
	}
	virtual void get(Property const *o, IPropertyConverter *propertyConverter, JsonValue &json) __THROW1
	{
		const TyClass *p = Property_cast<TyClass>(o);

		GDK_ASSERT(p != NULL);

		PropertyAttribute_get(this, (const Void*)&(p->*_propertyMember), propertyConverter, json);
	}
};

template<typename TyClass, typename TyProperty>
IPropertyAttribute::Handle createPropertyAttribute(
				TyProperty TyClass::*propertyMember,
				const String& propertyRawName,
				const String& propertyName,
				const String& description
			)
{
	return PropertyAttribute<TyClass, TyProperty>::createInstance(
				propertyMember,
				typeid_className<TyProperty>(),
				typeid_className<TyClass>() + __TEXT__("::") + propertyRawName,
				propertyName,
				description,
				true
			);
}
template<typename TyClass, typename TyProperty>
IPropertyAttribute::Handle createPropertyAttribute(
				gdk::Unknown::Handle_T<TyProperty> TyClass::*propertyMember,
				const String& propertyRawName,
				const String& propertyName,
				const String& description
			)
{
	typedef typename gdk::Unknown::Handle_T<TyProperty> TyProperty_Handle;
	return PropertyAttribute<TyClass, TyProperty_Handle>::createInstance(
				propertyMember,
				typeid_className<TyProperty>(),
				typeid_className<TyClass>() + __TEXT__("::") + propertyRawName,
				propertyName,
				description,
				false
			);
}


//----------------------------------------------
GDK_CORE_EXPORT void ProcessPropertyAttribute_set(IPropertyAttribute *propertyAttribute, const String &procParmClassName, Void *o, const JsonValue &json) __THROW1;
GDK_CORE_EXPORT void ProcessPropertyAttribute_get(IPropertyAttribute *propertyAttribute, const String &procParmClassName, const Void *o, JsonValue &json) __THROW1;


template<typename Ty>
void ProcessPropertyAttribute_set(IPropertyAttribute *propertyAttribute, void(Void::*set)(const Ty &), const String &procParmClassName, Void *o, const JsonValue &json) __THROW1
{
	Ty v;
	ProcessPropertyAttribute_set(propertyAttribute, procParmClassName, (Void*)&v, json);
	(o->*set)(v);
}
template<typename Ty>
void ProcessPropertyAttribute_get(IPropertyAttribute *propertyAttribute, Ty(Void::*get)(void) const, const String &procParmClassName, const Void *o, JsonValue &json) __THROW1
{
	Ty v = (o->*get)();
	ProcessPropertyAttribute_get(propertyAttribute, procParmClassName, (const Void*)&v, json);
}

template<typename TyClass, typename TyProperty>
class ProcessPropertyAttribute : public IPropertyAttribute
{
	typedef void(TyClass::*Set)(const TyProperty &);
	typedef TyProperty(TyClass::*Get)(void) const;

	DECLARE_CLASS_HANDLE(ProcessPropertyAttribute)
	DECLARE_CLASS_INSTANCE5(ProcessPropertyAttribute, Set, Get, const String&, const String&, const String&)

private:
	const Set     _set;
	const Get     _get;
	const String  _className;

private:
	ProcessPropertyAttribute(
			Set   set,
			Get   get,
			const String& rawName,
			const String& name,
			const String& description
		)
		: IPropertyAttribute(
			rawName,
			rawName,
			name,
			description,
			true
		)
		, _set(set)
		, _get(get)
		, _className(typeid_className<TyProperty>())
	{
	}

public:
	virtual void set(Property *o, IPropertyConverter *propertyConverter, const JsonValue &json) __THROW1
	{
		TyClass *p = Property_cast<TyClass>(o);

		GDK_ASSERT( p != NULL );
		GDK_ASSERT( propertyConverter == NULL );

		struct{
			union{
				Set	set_;
				void (Void::*set)(const TyProperty &);
			};
		} u;
		u.set_ = _set;

		ProcessPropertyAttribute_set<TyProperty>(this, u.set, _className, (Void*)p, json);
	}
	virtual void get(const Property *o, IPropertyConverter *propertyConverter, JsonValue &json) __THROW1
	{
		const TyClass *p = Property_cast<TyClass>(o);

		GDK_ASSERT( p != NULL );
		GDK_ASSERT( propertyConverter == NULL );

		struct{
			union{
				Get	get_;
				TyProperty (Void::*get)(void) const;
			};
		} u;
		u.get_ = _get;

		ProcessPropertyAttribute_get<TyProperty>(this, u.get, _className, (const Void*)p, json);
	}
};


template<typename TyClass, typename TyProperty>
IPropertyAttribute::Handle createProcessPropertyAttribute(
				void(TyClass::*set)(const TyProperty &) __THROW1,
				TyProperty(TyClass::*get)(void) const __THROW1,
				const String& rawName,
				const String& name,
				const String& description
			)
{
	return ProcessPropertyAttribute<TyClass, TyProperty>::createInstance(
				set,
				get,
				typeid_className<TyClass>() + __TEXT__("::") + rawName,
				name,
				description
			);
}


typedef std::map<String, IPropertyAttribute::Handle>  PropertyAttributes;

#define DECLARE_PROPERTY(className) \
	private:\
		static gdk::PropertyAttributes g_propertyAttributes_;\
		static gdk::Mutex g_classProperties_mutex_;\
		static int32_t g_classProperties_flag_;\
		static gdk::String	g_propertyType;\
		static bool registerProperty_(void);\
	public:\
		static const bool g_registerProperty_;\
		virtual const gdk::PropertyAttributes& getPropertyAttributes(void) const;\
		virtual const gdk::String& getPropertyType(void) const { return g_propertyType; }\
	private:


#define IMPLEMENT_PROPERTY_BEGIN(className) \
	gdk::PropertyAttributes className::g_propertyAttributes_;\
	gdk::Mutex className::g_classProperties_mutex_;\
	int32_t className::g_classProperties_flag_;\
	gdk::String className::g_propertyType(__TEXT__(#className));\
	const bool className::g_registerProperty_ = registerProperty_();\
	const gdk::PropertyAttributes& className::getPropertyAttributes(void) const\
	{\
		return g_propertyAttributes_;\
	}\
	bool className::registerProperty_(void) {\
		typedef className ThisClass;\
		gdk::nothing((ThisClass*)0);  /*消除编译警告*/


#define IMPLEMENT_PROPERTY_BEGIN1(className,baseClass) \
	gdk::PropertyAttributes className::g_propertyAttributes_;\
	gdk::Mutex className::g_classProperties_mutex_;\
	int32_t className::g_classProperties_flag_;\
	gdk::String className::g_propertyType(__TEXT__(#className));\
	const bool className::g_registerProperty_ = registerProperty_();\
	const gdk::PropertyAttributes& className::getPropertyAttributes(void) const\
	{\
		if (!g_classProperties_flag_)\
		{\
			MUTEX_BEGIN(g_classProperties_mutex_)\
			{\
				if (!g_classProperties_flag_)\
				{\
					gdk::PropertyAttributeHelper::mergePropertyAttribute(g_propertyAttributes_, ((baseClass*)0)->baseClass::getPropertyAttributes());\
					g_classProperties_flag_ = 1;\
				}\
			}\
			MUTEX_END()\
		}\
		return g_propertyAttributes_;\
	}\
	bool className::registerProperty_(void) {\
		typedef className ThisClass;\
		gdk::nothing((ThisClass*)0);  /*消除编译警告*/


#define IMPLEMENT_PROPERTY_BEGIN2(className, baseClass1, baseClass2) \
	gdk::PropertyAttributes className::g_propertyAttributes_;\
	gdk::Mutex className::g_classProperties_mutex_;\
	int32_t className::g_classProperties_flag_;\
	gdk::String className::g_propertyType(__TEXT__(#className));\
	const bool className::g_registerProperty_ = registerProperty_();\
	const gdk::PropertyAttributes& className::getPropertyAttributes(void) const\
	{\
		if (!g_classProperties_flag_)\
		{\
			MUTEX_BEGIN(g_classProperties_mutex_)\
			{\
				if (!g_classProperties_flag_)\
				{\
					gdk::PropertyAttributeHelper::mergePropertyAttribute(g_propertyAttributes_,((baseClass1*)0)->baseClass::getPropertyAttributes());\
					gdk::PropertyAttributeHelper::mergePropertyAttribute(g_propertyAttributes_,((baseClass2*)0)->baseClass::getPropertyAttributes());\
					g_classProperties_flag_ = 1;\
				}\
			}\
			MUTEX_END()\
		}\
		return g_propertyAttributes_;\
	}\
	bool className::registerProperty_(void) {\
		typedef className ThisClass;\
		gdk::nothing((ThisClass*)0);  /*消除编译警告*/


#define IMPLEMENT_PROPERTY_ATTRIBUTE_(member,memberName,description) \
		{\
			gdk::PropertyAttributeHelper::registerPropertyAttribute(g_propertyAttributes_, gdk::createPropertyAttribute(&ThisClass::member, __TEXT__(#member), memberName, description));\
		}

#define IMPLEMENT_PROPERTY_PROCESS_(process, memberName, description) \
		{\
			gdk::PropertyAttributeHelper::registerPropertyAttribute(g_propertyAttributes_, gdk::createProcessPropertyAttribute(&ThisClass::process, &ThisClass::process, __TEXT__(#process), memberName, description));\
		}

#define IMPLEMENT_PROPERTY_ATTRIBUTE(member, description) \
		{\
			gdk::String memberName(__TEXT__(#member));\
			gdk::PropertyAttributeHelper::registerPropertyAttribute(g_propertyAttributes_, gdk::createPropertyAttribute(&ThisClass::member, memberName, memberName, description));\
		}

#define IMPLEMENT_PROPERTY_PROCESS(member, description) \
		{\
			gdk::String memberName(__TEXT__(#member));\
			gdk::PropertyAttributeHelper::registerPropertyAttribute(g_propertyAttributes_, gdk::createProcessPropertyAttribute(&ThisClass::member, &ThisClass::member, memberName, memberName, description));\
		}

#define IMPLEMENT_PROPERTY_END() \
		return true;\
	};


#define REGISTER_PROPERTY(className) \
	static const bool g_##className##_registerProperty_ = (gdk::nothing(&g_##className##_registerProperty_), className::g_registerProperty_);\
	typedef std::vector<className::Handle>  className##Array;\
	typedef std::list<className::Handle>    className##List;



class PropertyAttributeHelper
{
public:
	GDK_CORE_EXPORT static void mergePropertyAttribute(PropertyAttributes &o, const PropertyAttributes &propertyAttributes)
	{
		typedef PropertyAttributes::const_iterator Properties_ConstIterator;

		for (Properties_ConstIterator it = propertyAttributes.begin(); it != propertyAttributes.end(); ++it)
		{
			if (o.find(it->first) == o.end())
				o[it->first] = it->second;
			else
				GDK_ASSERT(false);
		}
	}
	GDK_CORE_EXPORT static void registerPropertyAttribute(PropertyAttributes &o, IPropertyAttribute *propertyAttribute)
	{
		GDK_ASSERT(propertyAttribute != NULL);
		GDK_ASSERT(o.find(propertyAttribute->getPropertyName()) == o.end());

		o[propertyAttribute->getPropertyName()] = propertyAttribute;
	}
};

class GDK_CORE_EXPORT Property : virtual public Unknown
{
	DECLARE_CLASS_HANDLE(Property)
	DECLARE_CLASS_INSTANCE(Property)
	DECLARE_RT_CREATOR(Property)
	DECLARE_PROPERTY(Property)

public:
	void importProperty(const JsonValue &json);
	void exportProperty(JsonValue &json) const;
};
REGISTER_PROPERTY(Property);



class PropertyHelper
{
public:
	GDK_CORE_EXPORT static Property::Handle convertPropertyToClass(const JsonValue &json);
	GDK_CORE_EXPORT static void convertPropertyToJson(const Property *o, JsonValue &json);

	GDK_CORE_EXPORT static String convertToString(const Property *o, bool indent = false);
	GDK_CORE_EXPORT static Property::Handle convertToClass(const String &text);

	GDK_CORE_EXPORT static bool write(const Property *o, Output *out, bool indent = false);
	GDK_CORE_EXPORT static Property::Handle read(Input *in);

	GDK_CORE_EXPORT static bool save(const Property *o, const String &fileName, bool indent = false);
	GDK_CORE_EXPORT static Property::Handle load(const String &fileName);
};


//--------------------------------------------------------------
__INLINE__ void convertPropertyToClass(const JsonValue& json, std::vector<bool> &value) __THROW1
{
	typedef std::vector<bool>::value_type Tyvalue;
	typedef std::vector<bool>::iterator iterator;

	value.clear();

	if (json.isArray())
	{
		ssize_t i = 0;
		value.resize(json.size());
		for (iterator it = value.begin(); it != value.end(); ++it)
		{
			Tyvalue v;
			convertPropertyToClass(json[i ++], v);
			(*it) = v;
		}
	}
}
template<typename Ty>
void convertPropertyToClass(const JsonValue& json, Ty &value) __THROW1
{
	typedef typename Ty::value_type Tyvalue;
	typedef typename Ty::iterator iterator;

	value.clear();

	if (json.isArray())
	{
		ssize_t i = 0;
		value.resize(json.size());
		for (iterator it = value.begin(); it != value.end(); ++it)
		{
			/*
			Tyvalue v;
			convertPropertyToClass(json[i ++], v);
			(*it) = v;
			*/
			convertPropertyToClass(json[i ++], (Tyvalue&)(*it));
		}
	}
}
template<typename Ty> class ConvertPropertyToJson {
	JsonValue *json;
	int idx;
public:
	ConvertPropertyToJson(JsonValue &v)
		: json(&v)
		, idx(0)
	{}
    void operator () (const Ty &value) __THROW1
    {
		JsonValue v;
		convertPropertyToJson(value, v);
		json->operator[] (idx ++).swap(v);
    }
    __INLINE__ operator JsonValue& () { return *json; }
};
template<typename Ty>
void convertPropertyToJson(const Ty &value, JsonValue &json) __THROW1
{
/*	// Xcode 下设置 Compiler 为 LLVM C++ 编译出错
	typedef typename Ty::const_iterator	const_iterator;

	JsonValue tmp(JsonValue::arrayValue);
	json.swap(tmp);

	ssize_t idx = 0;
    for (const_iterator it = value.begin(); it != value.end(); ++it)
	{
		convertPropertyToJson(*it, json[idx ++]);
	}
*/
	JsonValue tmpjson(JsonValue::arrayValue);
	ConvertPropertyToJson<typename Ty::value_type> func(tmpjson);
	json.swap(std::for_each(value.begin(), value.end(), func));
}


//======================================================================
template<typename Ty>
void convertPropertyToClass(const JsonValue &json, SharedPtr<Ty> &o) __THROW1
{
	if (!json.isNull())
	{
		o = SharedPtr<Ty>(GDK_NEW Ty());
		convertPropertyToClass(json, *o);
	}
	else if (!o.isNull())
	{
		o.setNull();
	}
}
template<typename Ty>
void convertPropertyToJson(const SharedPtr<Ty> &o, JsonValue &json) __THROW1
{
	if (!o.isNull())
	{
		convertPropertyToJson(*o, json);
	}
	else
	{
		json.clear();
	}
}

//------------------------------------------------------------
template<typename Ty>
void convertPropertyToClass(const JsonValue &json, gdk::Unknown::Handle_T<Ty> &o) __THROW1
{
	o = PropertyHelper::convertPropertyToClass(json).dynamicCast<Ty>();
}
template<typename Ty>
void convertPropertyToJson(const gdk::Unknown::Handle_T<Ty> &o, JsonValue &json) __THROW1
{
	PropertyHelper::convertPropertyToJson(o, json);
}


//------------------------------------------------------------
template<typename TyKey, typename TyValue>
void convertPropertyToClass(const JsonValue &json, std::map<TyKey, TyValue> &o) __THROW1
{
	o.clear();

	if (json.isObject())
	{
		const JsonValue::Members &members = json.getMembers();
		for (JsonValue::Members::const_iterator it = members.begin(); it != members.end(); ++it)
		{
			/*
			typedef typename std::pair<TyKey, TyValue> pair;

			pair v;
			convertPropertyToClass(it->first, v.first);
			convertPropertyToClass(it->second, v.second);
			o.insert(v);
			*/
			TyKey k;
			convertPropertyToClass(it->first, k);
			convertPropertyToClass(it->second, o[k]);
		}
	}
}
template<typename TyKey, typename TyValue>
void convertPropertyToJson(const std::map<TyKey, TyValue> &o, JsonValue &json) __THROW1
{
	typedef typename std::map<TyKey, TyValue>::const_iterator const_iterator;

	JsonValue tmp(JsonValue::objectValue);
	json.swap(tmp);

	for (const_iterator it = o.begin(); it != o.end(); ++it)
	{
		JsonValue k, v;
		convertPropertyToJson(it->first, k);
		convertPropertyToJson(it->second, v);
		json[k.asString()].swap(v);
	}
}





}//namespace gdk



#endif /*__GDK_PROPERTY_H__*/
